package cn.sym.basic.service.impl;

import cn.sym.basic.baseConstant.BaseConstant;
import cn.sym.basic.dto.RegisterDto;
import cn.sym.basic.exception.MyException;
import cn.sym.basic.service.IVerifyCodeService;
import cn.sym.basic.util.StrUtils;
import cn.sym.basic.util.VerifyCodeUtils;
import cn.sym.user.domain.Logininfo;
import cn.sym.user.mapper.LogininfoMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.concurrent.TimeUnit;

@Service
public class VerifyCodeServiceImpl implements IVerifyCodeService {
        @Autowired
        private RedisTemplate redisTemplate;
        @Autowired
        private LogininfoMapper logininfoMapper;

    /**
     * 获取图片验证码
     * @param key
     * @return
     */
    @Override
        public String getImgCode(String key) {
            if (!StringUtils.hasLength(key)){
                throw new MyException("参数为空！");
            }
            //产生验证码
            String code = VerifyCodeUtils.generateVerifyCode(4);
            //存放redis
            redisTemplate.opsForValue().set(key, code, 5, TimeUnit.MINUTES);
            try {
                //把生成验证码的值合并到图片，然后使用base64编码，并返回base64编码的字符串
                return VerifyCodeUtils.VerifyCode(100,40, code);
            } catch (MyException e) {
                e.printStackTrace();
                throw new RuntimeException("图片验证码创建失败");
            }
        }

    /**
     * 发送短信
     * @param registerDto
     */
    @Override
    public void sendSmsCode(RegisterDto registerDto) {
        //前端传入的业务类型  register  login
        String type = registerDto.getType();
        if("register".equals(type)){
            sendRegisterSmsCode(registerDto);
        }else if("binder".equals(type)){
            sendBinderSmsCode(registerDto);
        }
    }

    /**
     * 发送微信绑定短信验证码
     * @param registerDto
     */
    private void sendBinderSmsCode(RegisterDto registerDto) {
        //发送短信验证码
        String smscodeKey = BaseConstant.SmsConstant.BUSINESS_BINDER_PREFIX+registerDto.getPhone();
        SmsCode(smscodeKey);
    }

    /**
     * 发送注册短信验证码
     * @param registerDto
     */
    private void sendRegisterSmsCode(RegisterDto registerDto) {
        //先拿到前端传入的图片验证码，电话号码，存放图片验证码的key
        String imageCode = registerDto.getImageCode();
        String imageCodeKey = registerDto.getImageKey();
        String phone = registerDto.getPhone();
        //1.先做空值判断
        if (StringUtils.isEmpty(imageCode)){
            System.out.println("图片验证码不可以为空");
        }
        if (StringUtils.isEmpty(imageCodeKey)){
            System.out.println("请刷新页面重新获取图片验证码");
        }
        if (StringUtils.isEmpty(phone)){
            System.out.println("手机号不能为空");
        }
        //2.根据用户传入的手机号去查询数据库看此手机号是否已经被注册了
        Logininfo logininfo = logininfoMapper.loadByPhone(phone);
        if (logininfo!=null){
            throw new MyException("此手机号已经被注册，请直接登录！！");
        }
        //3.校验图形验证码--不要区分大小写
        Object imgValue = redisTemplate.opsForValue().get(registerDto.getImageKey());
        if (imgValue==null){
            throw new MyException("验证码已经失效，请重新获取验证码！！");
        }
        //在忽视大小写的情况下，如果redis里面存储的验证码与用户输入的验证码不相同
        if (!imgValue.toString().equalsIgnoreCase(registerDto.getImageCode())){
            throw new MyException("请输入正确的验证码！！");
        }
        //发送短信验证码
        String smscodeKey = BaseConstant.SmsConstant.BUSINESS_REGISTER_PREFIX+phone;
        SmsCode(smscodeKey);
    }

    /**
     * 发送短信验证码--公共
     * @param smscodeKey
     */
    private void SmsCode(String smscodeKey) {
        //4.校验短信码是否有效   ---用发送验证码的时间戳-当前的时间戳
        //  4.1拼接验证码  register:13890796484
        String smsCodeKey = smscodeKey;
        Object smsCodeValue = redisTemplate.opsForValue().get(smsCodeKey);
        String code = "";//短信验证码
        //4.2如果通过拼接的key拿到的值不为空，说明还没有过期
        if (smsCodeValue!=null){
            //发送验证码时的时间戳
            Long oldTime = Long.valueOf(smsCodeValue.toString().split(":")[1]);
            //如果发送时间间隔不到1分钟
            if (System.currentTimeMillis()-oldTime<=1*60*1000){
                //告诉用户不能重复发送
                throw new MyException("请不要重复发送验证码！！");
            }
            code = smsCodeValue.toString().split(":")[0];
        }else{
            //4.3如果没有拿到值就表示验证码已经生效  就需要重新生成验证码，存储redis，给他发短信
            code = StrUtils.getComplexRandomString(4);
        }
        //5.存储redis并发送短信
        String newCode = code+":"+System.currentTimeMillis();
        redisTemplate.opsForValue().set(smsCodeKey,code,3,TimeUnit.MINUTES);
        //SmsUtil.sendSms(phone,"您好！！，您的验证码是："+code+"，请在三分钟内使用！！！！");
        System.out.println("您好！！，您的验证码是："+code+"，请在三分钟内使用！！！！");
    }

}
